package fi.iki.joker.mobilogger.blogs;

import java.net.MalformedURLException;
import java.net.URL;
import java.util.Hashtable;
import java.util.Map;

import org.apache.xmlrpc.XmlRpcException;
import org.apache.xmlrpc.client.XmlRpcClient;
import org.apache.xmlrpc.client.XmlRpcClientConfigImpl;
import org.apache.xmlrpc.client.XmlRpcCommonsTransportFactory;

import android.app.Activity;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.Rect;
import android.util.AttributeSet;
import android.util.Log;
import android.widget.EditText;
import android.widget.TableLayout;
import android.widget.TableRow;
import android.widget.TextView;
import fi.iki.joker.mobilogger.db.BlogConfigBean;
import fi.iki.joker.mobilogger.db.DBUtil;

public class MetaWeblogCompliantAPI implements BlogInterface {

	private final String TAG = "MetaWeblogCompliantAPI";
	private Activity parentRef;
	private String XMLRPCUrl = null;
	private final int CONFIG_URL_ID = 101;
	
	public static class MyUrlText extends EditText {
        private Rect mRect;
        private Paint mPaint;

        // we need this constructor for ViewInflate
        public MyUrlText(Context context, AttributeSet attrs) {
            super(context, attrs);

            mRect = new Rect();
            mPaint = new Paint();
            mPaint.setStyle(Paint.Style.STROKE);
            mPaint.setColor(0xFF0000FF);
        }

        public MyUrlText(Context context) {
            super(context);

            mRect = new Rect();
            mPaint = new Paint();
            mPaint.setStyle(Paint.Style.STROKE);
            mPaint.setColor(0xFF0000FF);
        }
        
        @Override
        protected void onDraw(Canvas canvas) {

            int count = getLineCount();
            Rect r = mRect;
            Paint paint = mPaint;

            for (int i = 0; i < count; i++) {
                int baseline = getLineBounds(i, r);

                canvas.drawLine(r.left, baseline + 1, r.right, baseline + 1,
                                paint);
            }

            super.onDraw(canvas);
        }
    }
	
	public void createConfigEditorRows(Activity parent, TableLayout tl,
			Context context, int startIdFrom, int populateFromId) {
		this.parentRef = parent;
		String configURLText = null;
		if(populateFromId > 0) {
			DBUtil db = new DBUtil();
			BlogConfigBean tempConfigBean = null;
			if(db.isDatabaseReady(parentRef)) {
				 tempConfigBean = db.getBlogConfigById(populateFromId);
			}
			configURLText = tempConfigBean.getPostConfig().toString();
		} else {
			configURLText = "";
		}
		TableRow tr1 = new TableRow(context);
		TableRow tr2 = new TableRow(context);
    	tr1.setId(startIdFrom);
    	tr2.setId(startIdFrom+1);
		TextView title = new TextView(context);
		TextView help = new TextView(context);
		// Create field to read url from user
		MyUrlText urlField = new MyUrlText(context);
		title.setText("XML-RPC\nendpoint URL:");
		help.setText("This is the full\npath to the\nXML-RPC server.");
		urlField.setText(configURLText);
		urlField.setId(CONFIG_URL_ID);
		TableRow.LayoutParams firstRowLayoutParams = new TableRow.LayoutParams(); 
		firstRowLayoutParams.width = firstRowLayoutParams.WRAP_CONTENT;
		TableRow.LayoutParams secondRowLayoutParams = new TableRow.LayoutParams(); 
		tr1.addView(title, firstRowLayoutParams);
		tr1.addView(urlField, firstRowLayoutParams);
		secondRowLayoutParams.span = 2;
		tr2.addView(help, secondRowLayoutParams);
		tl.addView(tr1, new TableLayout.LayoutParams());
		tl.addView(tr2, new TableLayout.LayoutParams());
	}



	public void setInstanceConfig(CharSequence config) {
		Log.d(TAG,"Setting instance config: "+config);
		// sanity checking whether this is an url...
		if(config != null) {
			try {
				URL tempurl = new URL(config.toString());
			} catch (MalformedURLException mue) {
				Log.e(TAG,"setInstanceConfig parameter doesn't look like an URL...");
				//throw new IllegalArgumentException("The instance config should be an URL but it"+
				//"doesn't really look like it. ("+config.toString()+")");
			}
			this.XMLRPCUrl = config.toString();
		} else {
			Log.e(TAG,"setInstanceConfig called with null argument!");
			//throw new IllegalArgumentException("You can't set a null instance config"+
			//		" since that would leave this object to null state. Try setting the post's"+
			//		" XML-RPC url.");
		}
	}



	public boolean createPost(Activity parent, String authToken,
			String postUrl, String titleType, String title, String contentType,
			String content, String authorName, String authorEmail,
			boolean isDraft) {
		// TODO Auto-generated method stub
		String username = "unassigned";
		String password = "unassigned";
		if(authToken.matches("(.*)\\|\\|(.*)")) {
			String[] splt = authToken.split("\\|\\|");
			username = splt[0];
			Log.d(TAG,"Set username from config: "+username);
			password = splt[1];
			Log.d(TAG,"Set password from config: "+password);
		} else {
			Log.e(TAG,"Cannot parse username and password from the auth token!");
		}
		XmlRpcClientConfigImpl config = new XmlRpcClientConfigImpl();
	    // check the config var
		String localPostUrl = getPostUrl(authToken);
		try {
	    	config.setServerURL(new URL(localPostUrl));
	    } catch (MalformedURLException e) {
	    	Log.e(TAG,"Unable to configure XML-RPC client! Post URL ("+localPostUrl+") is invalid.");
	    }
	    //The blog id number, as String
	    String blogIdNum = "1";
	    Boolean publish = new Boolean(true);
	    if(isDraft) {
	    	publish = new Boolean(false);
	    } else {
	    	publish = new Boolean(true);
	    }
	    Hashtable<String, String> struct = new Hashtable<String,String>(); 
		if(title != null) {
			struct.put("title", title);
		} else {
			struct.put("title", "");
		}
		if(content != null) {
			struct.put("description", content.toString());
		} else {
			struct.put("description", "");
		}
		if(authorName != null) {
			struct.put("author", authorName);
		} else {
			struct.put("author", authorName);
		}
			
	    XmlRpcClient client = new XmlRpcClient();
		Object [] params = new Object[] {
			""+blogIdNum,
			username,
			password,
			struct,
			publish
		};
		client.setTransportFactory(new XmlRpcCommonsTransportFactory(client));
		client.setConfig(config);
		String postID = null;
		try {
			postID = (String) client.execute( "metaWeblog.newPost", params );
		} catch (XmlRpcException e) {
			Log.e(TAG,"Exception while executing xml RPC call!");
			Log.d(TAG,"Exception message:"+e.getMessage());
			return false;
		}
		try {
			if((postID == null)||postID.equals("")) { 
				Log.e(TAG,"XML-RPC client returned null or void return code.");
				return false;
			} else if((Integer.parseInt(postID))>0){
				Log.d(TAG,"XML-RPC client returned postID:"+postID);
				return true;
			}
		} catch (NumberFormatException e) {
			Log.e(TAG,"XML-RPC client returned non-numeric return code: "+postID);
			return false;
		}
		Log.e(TAG, "Fallback return executed, should not happen!");
		return false;
	}

	public String getAuthId(String username, String password) {
		//since metaweblog api sends the credentials as part of the
		//createpost call, this just catenates the username and password with
		//||as field separator. This is then send to the createPost by caller
		//which again parses it.
		String res = username+"||"+password;
		return res;
	}

	public CharSequence getConfigEditorData() {
		// return URL field:
		EditText urlField = (EditText)(parentRef.findViewById(CONFIG_URL_ID));
		if(urlField == null) {
			Log.e(TAG,"Can't fetch the URL field in blog config editor from Blogger HTTPS api!");
		} else {
			return urlField.getText().toString();
		}
		return null;
	}

	public String getPostUrl(String authToken) {
		// This method fails in case the caller is using
		// a subclass of this API class (since the lookup from the
		// db is done using a config number) and the instance
		// of this class has not been prepared using the 
		// setinstanceconfig. (ths db call, in this case, returns
		// null. So beware.
		if(XMLRPCUrl == null) {
			String[] splt = authToken.split("\\|\\|");
			String username = splt[0];
			int typeid = BlogConfigConstants.getInterfaceNumberByType(BlogConfigConstants.BlogInterfaceType.METAWEBLOG);
			Log.d(TAG,"Set username from config: "+username);
			String password = splt[1];
			Log.d(TAG,"Set password from config: "+password);
			DBUtil db = new DBUtil();
			BlogConfigBean bcb = null;
			if(db.isDatabaseReady(parentRef)) {
				bcb = db.getBlogConfigByUserPassAndType(typeid, username, password);
			}
			if(bcb != null) {
				String res = bcb.getPostConfig().toString(); 
				Log.d(TAG,"This post will be published using XMLRPC endpoint:"+res);
				return res;
			} else {
				return null;
			}
		} else {
			// this is set by the setInstanceConfig method.
			Log.d(TAG,"Returning preset instance config: "+XMLRPCUrl);
			return this.XMLRPCUrl;
		}
	}
	
	

}
